
package maquina_virtualP1.gui;

import java.awt.Color;
import java.io.File;
import java.util.ArrayList;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import maquina_virtualP1.maquinap.Filtro;
import maquina_virtualP1.maquinap.MaquinaP;

/**
 * The application's main frame.
 * @author Miguel Angel Diaz Calvo
 */
public class MaquinaVirtualView extends javax.swing.JFrame {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JList jList1;
    private javax.swing.JList jList2;
    private javax.swing.JList jList3;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    
    private MaquinaVirtualManualBox manualBox;
    private MaquinaVirtualAboutBox aboutBox;
    
    private MaquinaP mp;
	
    private String ultimaRuta;
    
    private static boolean inicializado = false;
    
	/** Creates new form MaquinaVirtualView */
    public MaquinaVirtualView() {
    	mp = new MaquinaP();
    	ultimaRuta = "";
    	initComponents();
    	actualiza();
    	inicializado = true;
    }

    private void abrirArchivo(java.awt.event.ActionEvent evt) {
    	JFileChooser jFileChooser= new JFileChooser();
    	if (ultimaRuta.equals(""))
    		jFileChooser.setCurrentDirectory(new File("."));
    	else
    		jFileChooser.setCurrentDirectory(new File(ultimaRuta));
        jFileChooser.setMultiSelectionEnabled(false);
        jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        jFileChooser.setFileFilter(new Filtro());
        jFileChooser.showOpenDialog(this);
        try {
            String fichero = jFileChooser.getSelectedFile().getPath();
            mp.reinicia();
            mp.cargarPrograma(fichero);
            if (mp.programaCargado())
            	setTitle("M\u00e1quina Virtual 1.0 - " + jFileChooser.getSelectedFile().getName());
            ultimaRuta = jFileChooser.getSelectedFile().getParent();
            actualiza();          
        }
        catch (Exception e){            
        }
    }
    
    private void actualiza(){
    	
        // Actualiza la pila
        int filas = jScrollPane1.getHeight() / 18;
        int tamPila = mp.getPila().size();
        ArrayList<String> pila = new ArrayList<String>();
        for (int i=0; i<(filas-tamPila); i++)
            pila.add(" ");
        for (int i=tamPila-1; i>=0; i--)
            pila.add(i + "@  " + mp.getPila().get(i).toString());
        jList1.setListData(pila.toArray());
        jList1.setSelectedIndex(Math.max(filas - tamPila,0));
        jList1.ensureIndexIsVisible(Math.max(filas - tamPila,0));
        
        // Actualiza la memoria de instrucciones
        ArrayList<String> mInstr = new ArrayList<String>();
        int tamMI = mp.getMInstr().size();
        for (int i=0; i<tamMI; i++)
        	mInstr.add(i + "@  " + mp.getPosMInstr(i));
        jList2.setListData(mInstr.toArray());
        jList2.setSelectedIndex(mp.getCP());
        jList2.ensureIndexIsVisible(mp.getCP());
        
        // Actualiza la memoria de datos
        ArrayList<String> mDatos = new ArrayList<String>();
        int tamMD = mp.getMDatos().size();
        for (int i=0; i<tamMD; i++)
        	if (mp.getPosMDatos(i) != Integer.MIN_VALUE)
        		mDatos.add(i + "@  " + mp.getPosMDatos(i));
        	else
        		mDatos.add(i + "@");
        jList3.setListData(mDatos.toArray());
        
        // Actualiza el contador de programa
        jTextField2.setText(Integer.toString(mp.getCP()));
        jTextField2.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        
        // Actualiza el estado
        jTextField3.setText(mp.getF()+"");
        jTextField3.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        
        // Actualiza el mensaje de informacion y los botones
        jTextField1.setText(mp.getInfo());
    	if (mp.getF() == 'e')
        	jTextField1.setForeground(Color.red);
        else if (mp.getF() == 's')
            jTextField1.setForeground(Color.blue);
    	
    	// Actualiza el estado de los botones
    	if (ultimaRuta.equals("")){ 		// Antes de empezar
    		jButton1.setEnabled(false);
    		jButton2.setEnabled(false);
    	}
    	else if (mp.getF() == 'r'){ 		// Al cargar un archivo
    		jButton1.setEnabled(true);
    		jButton2.setEnabled(true);
    		jButton3.setEnabled(true);
    	}
    	else {								// Al terminar la ejecucion
    		jButton1.setEnabled(false);
    		jButton2.setEnabled(false);
    	}
    }

    private void showManualBox(java.awt.event.ActionEvent evt) {
        if (manualBox == null) {
            manualBox = new MaquinaVirtualManualBox(this, true);
            manualBox.setLocationRelativeTo(this);
        }
        manualBox.setVisible(true);
    }

    private void showAboutBox(java.awt.event.ActionEvent evt) {
        if (aboutBox == null) {
            aboutBox = new MaquinaVirtualAboutBox(this, true);
            aboutBox.setLocationRelativeTo(this);
        }
        aboutBox.setVisible(true);
    }

    private void ejecutarTodo(java.awt.event.ActionEvent evt) {
    	if (mp.programaCargado()){
        	mp.ejecutaPrograma();
        	actualiza();
        }
        else
        	JOptionPane.showMessageDialog(this, "No hay programa cargado", "Info", JOptionPane.INFORMATION_MESSAGE);
    }

    private void ejecutarPorPasos(java.awt.event.ActionEvent evt) {
    	if (mp.programaCargado()){
        	mp.ejecutaInstruccion();
        	actualiza();
        }
        else
        	JOptionPane.showMessageDialog(this, "No hay programa cargado", "Info", JOptionPane.INFORMATION_MESSAGE);
    }

    private void reiniciar(java.awt.event.ActionEvent evt) {
    	mp.reinicia();
        actualiza();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     */
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        jList2 = new javax.swing.JList();
        jLabel2 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jList3 = new javax.swing.JList();
        jLabel3 = new javax.swing.JLabel();
        jTextField1 = new javax.swing.JTextField();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jTextField2 = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        jTextField3 = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        jMenuItem2 = new javax.swing.JMenuItem();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setIconImage(new javax.swing.ImageIcon(util.Util.rutaTrabajo() + File.separator + "resources" + File.separator + "logo_small.png").getImage());

        setMinimumSize(new java.awt.Dimension(450, 347));
        setTitle("M\u00e1quina Virtual 1.0");
        setLocationRelativeTo(null);
        
        jButton1.setEnabled(false);
        jButton2.setEnabled(false);
        jButton3.setEnabled(false);
        
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                formComponentResized(evt);
            }
        });
        
        jLabel1.setText("Pila");

        jList1.setToolTipText("Contenido de la pila de operandos");
        jScrollPane1.setViewportView(jList1);

        jLabel2.setText("Memoria de Instrucciones");

        jList2.setToolTipText("Contenido de la memoria de instrucciones");
        jScrollPane2.setViewportView(jList2);

        jLabel3.setText("Memoria de Datos");

        jList3.setToolTipText("Contenido de la memoria de datos");
        jScrollPane3.setViewportView(jList3);

        jTextField1.setToolTipText("Informacion adicional");
        jTextField1.setText("");

        jButton1.setText("Ejecutar todo");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ejecutarTodo(evt);
            }
        });
	    jButton1.setToolTipText("Ejecuta todo seguido");

        jButton2.setText("Ejecutar por pasos");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ejecutarPorPasos(evt);
            }
        });
	    jButton2.setToolTipText("Ejecuta instrucci\u00f3n a instrucci\u00f3n");

        jButton3.setText("Reiniciar");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                reiniciar(evt);
            }
        });
	    jButton3.setToolTipText("Reinicia el estado de la m\u00e1quina virtual");

        jLabel4.setText("CP");

        jTextField2.setToolTipText("Valor actual del contador de programa");

        jLabel5.setText("Estado");

        jTextField3.setToolTipText("Valor actual del estado");

        jLabel7.setIcon(new javax.swing.ImageIcon(util.Util.rutaTrabajo()+File.separator+"resources"+File.separator+"logo_small.png"));

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jTextField1, javax.swing.GroupLayout.DEFAULT_SIZE, 480, Short.MAX_VALUE)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel1)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 77, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 154, Short.MAX_VALUE)
                            .addComponent(jLabel2))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel3)
                            .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 125, Short.MAX_VALUE))
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(mainPanelLayout.createSequentialGroup()
                                .addGap(10, 10, 10)
                                .addComponent(jLabel7, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(mainPanelLayout.createSequentialGroup()
                                .addGap(35, 35, 35)
                                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(jLabel5)
                                    .addComponent(jLabel4)
                                    .addComponent(jTextField2, javax.swing.GroupLayout.DEFAULT_SIZE, 49, Short.MAX_VALUE)
                                    .addComponent(jTextField3)))))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, 155, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButton2, javax.swing.GroupLayout.DEFAULT_SIZE, 156, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButton3, javax.swing.GroupLayout.DEFAULT_SIZE, 157, Short.MAX_VALUE)))
                .addContainerGap())
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jLabel3)
                        .addComponent(jLabel2))
                    .addComponent(jLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jLabel5)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 87, Short.MAX_VALUE)
                        .addComponent(jLabel7)
                        .addGap(7, 7, 7)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2)
                    .addComponent(jButton3))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        fileMenu.setText("Archivo");

        jMenuItem1.setText("Abrir");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                abrirArchivo(evt);
            }
        });
	    fileMenu.add(jMenuItem1);

        exitMenuItem.setText("Salir");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dispose();
            }
        });
	    fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        helpMenu.setText("Ayuda");

        jMenuItem2.setText("Manual");
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showManualBox(evt);
            }
        });
	    helpMenu.add(jMenuItem2);

        aboutMenuItem.setText("Acerca de");
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showAboutBox(evt);
            }
        });
	    helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 500, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGap(0, 0, 0)
                    .addComponent(mainPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGap(0, 0, 0)))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 347, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGap(0, 0, 0)
                    .addComponent(mainPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGap(0, 0, 0)))
        );

        pack();
    }
    
    private void formComponentResized(java.awt.event.ComponentEvent evt) {
    	if (inicializado)
    		actualiza();
    }
    
}
